﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Xml;
using LoveMusic.Models;
using GSearch;
namespace LoveMusic.Helpers
{
    public static class AllMusicAPI
    {
        #region Properties

        private static string _artistName
        {
            get;
            set;
        }

        private static string _html
        {
            get;
            set;
        }

        #endregion

        /// <summary>
        /// Fills the _html with html :). Must be exucuted first
        /// </summary>
        /// <param name="artistName"></param>
        public static AllMusicBin SearchRequest(string artistName)
        {
            try
            {
                GWebSearch gws = new GWebSearch();
                WebSearchArgs wsa = new WebSearchArgs();
                wsa.Terms = "site:allmusic.com " + artistName + " Overview";
                GWebResponse resp = gws.Search(wsa);

                if (resp.Response.Results.Length > 0)
                {
                    foreach (GWebResults result in resp.Response.Results)
                    {
                        if (result.Title.ToLower().IndexOf("allmusic") != -1)
                        {
                            _html = WebHelper.GetResponseStandard(result.UnescapedUrl);
                            _artistName = artistName;
                            return GetData();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "AllMusicApi exception artistName=" + _artistName);
                return null;
            }
            return null;
        }

        private static AllMusicBin GetData()
        {
            try
            {
                string genre = string.Empty;
                string middleString = string.Empty;
                string[] part;
                string[] subParts;
                AllMusicBin allMusicBin = new AllMusicBin();
                allMusicBin.ArtistName = _artistName;

                #region genre

                part = _html.Split(new string[] { "<div id=\"left-sidebar-list\" style=\"padding-bottom:5px;\">" }, StringSplitOptions.None);

                try
                {

                    subParts = part[1].Split(new string[] { "<ul><li><a href=\"" }, StringSplitOptions.None);
                    genre = WebHelper.GetMiddleString(subParts[1], ">", "<");
                }
                catch (Exception ex)
                {
                    TraceLog.TimeWrite(ex, "ALLMUSICAPI Similar artists");
                }
                #endregion

                #region Styles

                try
                {
                    allMusicBin.Styles = new List<string>();
                    middleString = WebHelper.GetMiddleString(part[2], "<ul>", "</ul>");
                    subParts = middleString.Split(new string[] { "<li>" }, StringSplitOptions.None);
                    string oneStyle = string.Empty;

                    for (int i = 1; i < subParts.Length; i++)
                    {
                        oneStyle = WebHelper.GetMiddleString(subParts[i], ">", "</a");
                        allMusicBin.Styles.Add(oneStyle);
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TimeWrite(ex, "ALLMUSICAPI Similar artists");
                }
                #endregion

                #region Category

                try
                {
                    switch (genre)
                    {
                        case "Avant-Garde": allMusicBin.Category = 15; break;
                        case "Blues": allMusicBin.Category = 9; break;
                        case "Country": allMusicBin.Category = 15; break;
                        case "Easy Listening": allMusicBin.Category = 20; break;
                        case "Electronic": allMusicBin.Category = GetTehnoTranceClub(allMusicBin.Styles); break;
                        case "Folk": allMusicBin.Category = 15; break;
                        case "International": allMusicBin.Category = 14; break;
                        case "Jazz": allMusicBin.Category = 9; break;
                        case "Latin": allMusicBin.Category = 15; break;
                        case "New Age": allMusicBin.Category = 19; break;
                        case "Pop/Rock": allMusicBin.Category = GetPopOrRockOrSka(allMusicBin.Styles); break;
                        case "R&B": allMusicBin.Category = 10; break;
                        case "Rap": allMusicBin.Category = 2; break;
                        case "Reggae": allMusicBin.Category = 4; break;
                        case "Stage & Screen": allMusicBin.Category = 19; break;
                        case "Vocal": allMusicBin.Category = GetPopOrBlues(allMusicBin.Styles); break;

                        #region classical

                        case "Classical Genre": allMusicBin.Category = 20; break;
                        case "Avant-Garde Music": allMusicBin.Category = 20; break;
                        case "Ballet": allMusicBin.Category = 20; break;
                        case "Band Music": allMusicBin.Category = 20; break;
                        case "Chamber Music": allMusicBin.Category = 20; break;
                        case "Choral": allMusicBin.Category = 20; break;
                        case "Film Score": allMusicBin.Category = 20; break;
                        case "Keyboard": allMusicBin.Category = 20; break;
                        case "Opera": allMusicBin.Category = 20; break;
                        case "Orchestral": allMusicBin.Category = 20; break;
                        case "Show/Musical": allMusicBin.Category = 20; break;
                        case "Symphony": allMusicBin.Category = 20; break;
                        case "Vocal Music": allMusicBin.Category = 20; break;

                        #endregion

                        default: allMusicBin.Category = 15; break;
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TimeWrite(ex, "ALLMUSICAPI Similar artists");
                }
                #endregion Category

                #region Moods
                try
                {
                    allMusicBin.Moods = new List<string>();
                    middleString = WebHelper.GetMiddleString(part[3], "<ul>", "</ul>");
                    subParts = middleString.Split(new string[] { "<li>" }, StringSplitOptions.None);
                    string oneMood = string.Empty;

                    for (int i = 1; i < subParts.Length; i++)
                    {
                        oneMood = WebHelper.GetMiddleString(subParts[i], ">", "</a");
                        allMusicBin.Moods.Add(oneMood);
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TimeWrite(ex, "ALLMUSICAPI Similar artists");
                }
                #endregion Moods

                #region Similar artists

                try
                {
                    allMusicBin.SimilarArtists = new List<string>();
                    subParts = _html.Split(new string[] { "<div class=\"large-list-subtitle\">Similar Artists</div>" }, StringSplitOptions.None);
                    middleString = WebHelper.GetMiddleString(subParts[1], "<ul>", "</ul>");
                    subParts = middleString.Split(new string[] { "<li>" }, StringSplitOptions.None);
                    string oneArtist = string.Empty;

                    for (int i = 1; i < subParts.Length; i++)
                    {
                        subParts[i] = subParts[i].Split(new string[] { "href" }, StringSplitOptions.None)[1];
                        oneArtist = WebHelper.GetMiddleString(subParts[i], ">", "</a");
                        allMusicBin.SimilarArtists.Add(oneArtist);
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TimeWrite(ex, "ALLMUSICAPI Similar artists");
                }

                #endregion

                #region Years
                try
                {
                    allMusicBin.YearsActive = new List<string>();
                    subParts = _html.Split(new string[] { "<div class=\"timeline-sub-active\"" }, StringSplitOptions.None);
                    string oneYear = string.Empty;

                    for (int i = 1; i < subParts.Length; i++)
                    {
                        oneYear = WebHelper.GetMiddleString(subParts[i], ">", "</div");
                        if (oneYear.Length == 2)
                            oneYear = "19" + oneYear;
                        allMusicBin.YearsActive.Add(oneYear);
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TimeWrite(ex, "Years");
                }
                #endregion

                #region born died
                try
                {
                    subParts = _html.Split(new string[] { "<td class=\"formed-sub\" style=\"padding-left:5px;\"" }, StringSplitOptions.None);

                    allMusicBin.Born = WebHelper.RemoveTags(WebHelper.GetMiddleString(subParts[1], ">", "</td")).Trim();
                    if (subParts.Length >= 2)
                        allMusicBin.Died = WebHelper.RemoveTags(WebHelper.GetMiddleString(subParts[2], ">", "</td")).Trim();
                }
                catch (Exception ex)
                {
                    TraceLog.TimeWrite(ex, "trouble born died in all music");
                }
                #endregion

                #region Biography

                try
                {
                    subParts = _html.Split(new string[] { "artistminibio\"><p" }, StringSplitOptions.None);
                    allMusicBin.MiniBio = WebHelper.RemoveTags(WebHelper.GetMiddleString(subParts[1], ">", "</p")).Replace(" ... Read More...", "").Trim();
                }
                catch (Exception ex)
                {
                    TraceLog.TimeWrite(ex, "bio");
                }

                #endregion

                return allMusicBin;
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "ALLMUSIC FINal exception artistName=" + _artistName);
                return null;
            }
        }

        #region Private helper methods

        private static int GetTehnoTranceClub(List<string> styles)
        {
            int numberOfClubs = 0;
            int numberOfTrance = 0;
            int numberOfHouse = 0;
            foreach (string style in styles)
            {
                if (style.ToLower().IndexOf("drum'n'bass") != -1)
                    return 16;
                if (style.ToLower().IndexOf("club") != -1)
                    numberOfClubs++;
                if (style.ToLower().IndexOf("trance") != -1 || style.ToLower().IndexOf("psychedelic") != -1)
                    numberOfTrance++;
                if (style.ToLower().IndexOf("house") != -1)
                    numberOfHouse++;
            }

            if (numberOfHouse >= numberOfTrance)
                return 18;
            else if (numberOfTrance >= numberOfClubs)
                return 17;

            return 7;
        }

        private static int GetPopOrBlues(List<string> styles)
        {
            int numberOfPops = 0;
            int numberOfBlues = 0;
            foreach (string style in styles)
            {
                if (style.ToLower().IndexOf("pop") != -1)
                    numberOfPops++;
                else if (style.ToLower().IndexOf("jazz") != -1 || style.ToLower().IndexOf("blues") != -1)
                    numberOfBlues++;
            }
            if (numberOfBlues >= numberOfPops)
                return 9;
            else
                return 3;
        }

        private static int GetPopOrRockOrSka(List<string> styles)
        {
            int numberOfRocks = 0;
            int numberOfPops = 0;

            foreach (string style in styles)
            {
                if (style.ToLower().IndexOf("ska") != -1)
                    return 5;
                if (style.ToLower().IndexOf("pop") != -1)
                    numberOfPops++;
                else if (style.ToLower().IndexOf("rock") != -1)
                    numberOfRocks++;
            }
            if (numberOfRocks >= numberOfPops)
                return 1;
            else
                return 3;
        }

        #endregion
    }
}